﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace VsxFactory.Modeling.Repository
{
    /// <summary>
    /// Classe DTO pour utilisation avec ADO Data Services
    /// </summary>
    [System.Data.Services.Common.HasStream]
    [System.Runtime.Serialization.DataContract]
    [Serializable]
    public class PackageInfo
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="PackageInfo"/> class.
        /// </summary>
        /// <param name="manifest">The manifest.</param>
        public PackageInfo(PackageManifest manifest)
        {
            Guard.ArgumentNotNull(manifest, "manifest");
            Name = manifest.Name;
            Description = manifest.Description;
            Version = manifest.Version;
            Kind = manifest.Kind;
            LicenseUrl = manifest.LicenseUrl;
            RequireLicenseAcceptance = manifest.RequireLicenseAcceptance;
            Authors = String.Join(";", manifest.Authors);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PackageInfo"/> class.
        /// </summary>
        public PackageInfo()
        {
        }

        /// <summary>
        /// Gets or sets the ID.
        /// </summary>
        /// <value>The ID.</value>
        public string ID { 
            get {
                var v = System.Version.Parse(Version);
                return String.Format("{0}-{1}", Name, v.ToString(2));
            }
            set { } // nécessaire pour OData
        }

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name.</value>
        public string Name { get; set; }
        /// <summary>
        /// Gets or sets the description.
        /// </summary>
        /// <value>The description.</value>
        public string Description { get; set; }
        /// <summary>
        /// Gets or sets the version.
        /// </summary>
        /// <value>The version.</value>
        public string Version { get; set; }
        /// <summary>
        /// Gets or sets the kind.
        /// </summary>
        /// <value>The kind.</value>
        public string Kind { get; set; }

        public string Authors { get; set; }

        public bool RequireLicenseAcceptance { get; set; }
        public string LicenseUrl { get; set; }
        public string RepositorySource { get; set; }

        public static PackageInfo CreateFromSlug(string slug)
        {
            string[] parts = slug.Split(new char[] { '~' });
            return new PackageInfo() { Name = parts[0], Version = parts[1], Kind = parts[2] };
        }

        internal string CreateSlug()
        {
            return string.Format("{0}~{1}~{2}", this.Name, this.Version, Kind);
        }
    }


    /// <summary>
    /// 
    /// </summary>
    internal class RepositoryInfoComparer : System.Collections.Generic.IEqualityComparer<PackageInfo>
    {
        /// <summary>
        /// Determines whether the specified objects are equal.
        /// </summary>
        /// <param name="x">The first object of type <paramref name="T"/> to compare.</param>
        /// <param name="y">The second object of type <paramref name="T"/> to compare.</param>
        /// <returns>
        /// true if the specified objects are equal; otherwise, false.
        /// </returns>
        public bool Equals(PackageInfo x, PackageInfo y)
        {
            // Check whether the compared objects reference the same data.
            if (Object.ReferenceEquals(x, y)) return true;

            // Check whether any of the compared objects is null.
            if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
                return false;

            // Check whether the products' properties are equal.
            return x.ID == y.ID && x.Version == y.Version;
        }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <param name="manifest">The manifest.</param>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public int GetHashCode(PackageInfo info)
        {
            // Check whether the object is null.
            if (Object.ReferenceEquals(info, null)) return 0;

            // Get the hash code for the Name field if it is not null.
            int hashName = info.Name == null ? 0 : info.Name.GetHashCode();

            // Get the hash code for the Code field.
            int hashVersion = info.Version == null ? 0 : info.Version.GetHashCode();

            // Calculate the hash code for the product.
            return hashVersion ^ hashName;
        }
    }

}
